using System;
using System.ComponentModel;
using Microsoft.Win32.SafeHandles;
using System.Runtime.InteropServices;
using System.Security.Permissions;

namespace qPrintComponent
{
    public sealed class qSafePrinterHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        private string _servername = null;
        internal bool canUpdate = false;

        private qSafeDriverInfos _DriverInfo1s;
        private qSafeDriverInfos _DriverInfo2s;
        private qSafeDriverInfos _DriverInfo3s;
        private qSafeDriverInfos _DriverInfo4s;
        private qSafeDriverInfos _DriverInfo5s;
        private qSafeDriverInfos _DriverInfo6s;
        //private qSafeDriverInfos _DriverInfo8s;

        private DriverInfo1 _DriverInfo1 ;
        private DriverInfo2 _DriverInfo2;
        private DriverInfo3 _DriverInfo3;
        private DriverInfo4 _DriverInfo4;
        private DriverInfo5 _DriverInfo5;
        private DriverInfo6 _DriverInfo6;
        //private DriverInfo8 _DriverInfo8;

        private PrinterInfo1 _PrinterInfo1;
        private PrinterInfo2 _PrinterInfo2;
        private PrinterInfo4 _PrinterInfo4;
        private PrinterInfo5 _PrinterInfo5;
        private PrinterInfo6 _PrinterInfo6;

        private PrinterInfoQ _PrinterInfoQ;

        
        internal qSafePrinterHandle() 
            : base(true) 
        {}

        internal qSafePrinterHandle(string printername)
            : base(true)
        {
            OpenPrinter(printername);
        }

        
        [return: MarshalAs(UnmanagedType.U1)]
        protected override bool ReleaseHandle()
        {
            // Only close printer if handle is valid
            if (IsInvalid) 
                return true;
            // If the closing failes, the ReleaseHandleFailed MDA will be activated
            if (!qStatic.ClosePrinter(this.handle))
                return false;
            this.SetHandle(IntPtr.Zero);
            return true; 
        }
        private bool OpenPrinter(string printername)
        {
            canUpdate = true;
            qPrinterDefaults printerDefaults = new qPrinterDefaults(true);
            if (qStatic.OpenPrinter(printername, out this.handle, ref printerDefaults))
            {
                ResetPrinterInfo();
                return true;
            }
            else
            {
                printerDefaults = new qPrinterDefaults(false);
                canUpdate = false;
                if (!qStatic.OpenPrinter(printername, out this.handle, ref printerDefaults))
                {
                    ResetPrinterInfo();
                    return false;
                }
            }
            ResetPrinterInfo();
            return true;
        }

        [TypeConverter(typeof(PrinterNameConverter))]
        public string PrinterName
        {
            get
            {
                if (this.IsInvalid) return "";
                if (PrinterInfo5 == null) return "";
                return PrinterInfo5.PrinterName;
            }
            set
            {
                if (value != PrinterName)
                {
                    this.ReleaseHandle();
                    OpenPrinter(value);
                }
            }
        }

        public void ResetPrinterInfo()
        {
            if (!IsInvalid)
            {
                _PrinterInfo5 = new PrinterInfo5(this);
                _PrinterInfo2 = new PrinterInfo2(this);
                _PrinterInfo4 = new PrinterInfo4(this);
                
                if (_servername != _PrinterInfo4.ServerName)
                {
                    _servername = _PrinterInfo4.ServerName;
                    _DriverInfo1s = new qSafeDriverInfos(_servername,1);
                    _DriverInfo2s = new qSafeDriverInfos(_servername, 2);
                    _DriverInfo3s = new qSafeDriverInfos(_servername, 3);
                    _DriverInfo4s = new qSafeDriverInfos(_servername, 4);
                    _DriverInfo5s = new qSafeDriverInfos(_servername, 5);
                    _DriverInfo6s = new qSafeDriverInfos(_servername, 6);
                    //_DriverInfo8s = new qSafeDriverInfos(_servername, 8);
                }
                if (_DriverInfo1s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo1 = (DriverInfo1)_DriverInfo1s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo1 = new DriverInfo1(this);
                if (_DriverInfo2s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo2 = (DriverInfo2)_DriverInfo2s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo2 = new DriverInfo2(this);
                if (_DriverInfo3s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo3 = (DriverInfo3)_DriverInfo3s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo3 = new DriverInfo3(this); ;
                if (_DriverInfo4s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo4 = (DriverInfo4)_DriverInfo4s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo4 = new DriverInfo4(this);
                if (_DriverInfo5s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo5 = (DriverInfo5)_DriverInfo5s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo5 = new DriverInfo5(this);
                if (_DriverInfo6s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                    _DriverInfo6 = (DriverInfo6)_DriverInfo6s.Drivers[_PrinterInfo2.DriverName];
                else
                    _DriverInfo6 = new DriverInfo6(this);
                //if (_DriverInfo8s.Drivers.ContainsKey(_PrinterInfo2.DriverName))
                //    _DriverInfo8 = (DriverInfo8)_DriverInfo8s.Drivers[_PrinterInfo2.DriverName];
                //else
                //    _DriverInfo8 = new DriverInfo8(this);// null;
                _PrinterInfo1 = new PrinterInfo1(this);
                _PrinterInfo6 = new PrinterInfo6(this);
                _PrinterInfoQ = new PrinterInfoQ(_PrinterInfo5);
            }
            else
            {
                canUpdate = false;
                _DriverInfo1 = null;
                _DriverInfo2 = null;
                _DriverInfo3 = null;
                _DriverInfo4 = null;
                _DriverInfo5 = null;
                _DriverInfo6 = null;
                //_DriverInfo8 = null;

                _PrinterInfo1 = null;
                _PrinterInfo2 = null;
                _PrinterInfo4 = null;
                _PrinterInfo5 = null;
                _PrinterInfo6 = null;
                _PrinterInfoQ = null;
            }
        }

        [Browsable(false)]
        internal string PortName
        {
            get 
            {
                if (this.IsInvalid) return "";
                return PrinterInfo5.PortName;
            }
        }

        
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public PrinterInfo1 PrinterInfo1
        {
            get {return _PrinterInfo1;}
        }
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        [Description("Maximal printer information")]
        public PrinterInfo2 PrinterInfo2
        {
            get { return _PrinterInfo2; }
        }
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        [Description("Minimal printer information")]
        public PrinterInfo4 PrinterInfo4
        {
            get { return _PrinterInfo4; }
        }
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public PrinterInfo5 PrinterInfo5
        {
            get { return _PrinterInfo5; }
        }
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        [Description("The status value of a printer.")]
        public PrinterInfo6 PrinterInfo6
        {
            get { return _PrinterInfo6; }
        }
        [Category("Printer"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public PrinterInfoQ PrinterInfoQ
        {
            get { return _PrinterInfoQ; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo1 DriverInfo1
        {
            get { return _DriverInfo1; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo2 DriverInfo2
        {
            get { return _DriverInfo2; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo3 DriverInfo3
        {
            get { return _DriverInfo3; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo4 DriverInfo4
        {
            get { return _DriverInfo4; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo5 DriverInfo5
        {
            get { return _DriverInfo5; }
        }
        [Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        public DriverInfo6 DriverInfo6
        {
            get { return _DriverInfo6; }
        }
        //[Category("Driver"), TypeConverter(typeof(ExpandableObjectConverter)), Browsable(true)]
        //public DriverInfo8 DriverInfo8
        //{
        //    get {return _DriverInfo8;}
        //}
        public Boolean CanUpdate
        {
            get { return canUpdate; }
        }

   }  
}
